#include "sh1106.h"
#include <string.h>
#include "../../CLOCK/clock.h"  // 添加时钟驱动头文件

// 显示缓冲区
static uint8_t sh1106_buffer[SH1106_PAGES][SH1106_WIDTH];

// 6x8字体 (ASCII 32-127)
static const uint8_t font_6x8[][6] = {
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // space
    {0x00, 0x00, 0x2f, 0x00, 0x00, 0x00}, // !
    {0x00, 0x07, 0x00, 0x07, 0x00, 0x00}, // "
    {0x14, 0x7f, 0x14, 0x7f, 0x14, 0x00}, // #
    {0x24, 0x2a, 0x7f, 0x2a, 0x12, 0x00}, // $
    {0x62, 0x64, 0x08, 0x13, 0x23, 0x00}, // %
    {0x36, 0x49, 0x55, 0x22, 0x50, 0x00}, // &
    {0x00, 0x05, 0x03, 0x00, 0x00, 0x00}, // '
    {0x00, 0x1c, 0x22, 0x41, 0x00, 0x00}, // (
    {0x00, 0x41, 0x22, 0x1c, 0x00, 0x00}, // )
    {0x14, 0x08, 0x3E, 0x08, 0x14, 0x00}, // *
    {0x08, 0x08, 0x3E, 0x08, 0x08, 0x00}, // +
    {0x00, 0x00, 0xA0, 0x60, 0x00, 0x00}, // ,
    {0x08, 0x08, 0x08, 0x08, 0x08, 0x00}, // -
    {0x00, 0x60, 0x60, 0x00, 0x00, 0x00}, // .
    {0x20, 0x10, 0x08, 0x04, 0x02, 0x00}, // /
    {0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00}, // 0
    {0x00, 0x42, 0x7F, 0x40, 0x00, 0x00}, // 1
    {0x42, 0x61, 0x51, 0x49, 0x46, 0x00}, // 2
    {0x21, 0x41, 0x45, 0x4B, 0x31, 0x00}, // 3
    {0x18, 0x14, 0x12, 0x7F, 0x10, 0x00}, // 4
    {0x27, 0x45, 0x45, 0x45, 0x39, 0x00}, // 5
    {0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00}, // 6
    {0x01, 0x71, 0x09, 0x05, 0x03, 0x00}, // 7
    {0x36, 0x49, 0x49, 0x49, 0x36, 0x00}, // 8
    {0x06, 0x49, 0x49, 0x29, 0x1E, 0x00}, // 9
    {0x00, 0x36, 0x36, 0x00, 0x00, 0x00}, // :
    {0x00, 0x56, 0x36, 0x00, 0x00, 0x00}, // ;
    {0x08, 0x14, 0x22, 0x41, 0x00, 0x00}, // <
    {0x14, 0x14, 0x14, 0x14, 0x14, 0x00}, // =
    {0x00, 0x41, 0x22, 0x14, 0x08, 0x00}, // >
    {0x02, 0x01, 0x51, 0x09, 0x06, 0x00}, // ?
    {0x32, 0x49, 0x59, 0x51, 0x3E, 0x00}, // @
    {0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00}, // A
    {0x7F, 0x49, 0x49, 0x49, 0x36, 0x00}, // B
    {0x3E, 0x41, 0x41, 0x41, 0x22, 0x00}, // C
    {0x7F, 0x41, 0x41, 0x22, 0x1C, 0x00}, // D
    {0x7F, 0x49, 0x49, 0x49, 0x41, 0x00}, // E
    {0x7F, 0x09, 0x09, 0x09, 0x01, 0x00}, // F
    {0x3E, 0x41, 0x49, 0x49, 0x7A, 0x00}, // G
    {0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00}, // H
    {0x00, 0x41, 0x7F, 0x41, 0x00, 0x00}, // I
    {0x20, 0x40, 0x41, 0x3F, 0x01, 0x00}, // J
    {0x7F, 0x08, 0x14, 0x22, 0x41, 0x00}, // K
    {0x7F, 0x40, 0x40, 0x40, 0x40, 0x00}, // L
    {0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x00}, // M
    {0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00}, // N
    {0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00}, // O
    {0x7F, 0x09, 0x09, 0x09, 0x06, 0x00}, // P
    {0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00}, // Q
    {0x7F, 0x09, 0x19, 0x29, 0x46, 0x00}, // R
    {0x46, 0x49, 0x49, 0x49, 0x31, 0x00}, // S
    {0x01, 0x01, 0x7F, 0x01, 0x01, 0x00}, // T
    {0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00}, // U
    {0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00}, // V
    {0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00}, // W
    {0x63, 0x14, 0x08, 0x14, 0x63, 0x00}, // X
    {0x07, 0x08, 0x70, 0x08, 0x07, 0x00}, // Y
    {0x61, 0x51, 0x49, 0x45, 0x43, 0x00}, // Z
    {0x00, 0x7F, 0x41, 0x41, 0x00, 0x00}, // [
    {0x02, 0x04, 0x08, 0x10, 0x20, 0x00}, // "\"
    {0x00, 0x41, 0x41, 0x7F, 0x00, 0x00}, // ]
    {0x04, 0x02, 0x01, 0x02, 0x04, 0x00}, // ^
    {0x40, 0x40, 0x40, 0x40, 0x40, 0x00}, // _
    {0x00, 0x01, 0x02, 0x04, 0x00, 0x00}, // '
    {0x20, 0x54, 0x54, 0x54, 0x78, 0x00}, // a
    {0x7F, 0x48, 0x44, 0x44, 0x38, 0x00}, // b
    {0x38, 0x44, 0x44, 0x44, 0x20, 0x00}, // c
    {0x38, 0x44, 0x44, 0x48, 0x7F, 0x00}, // d
    {0x38, 0x54, 0x54, 0x54, 0x18, 0x00}, // e
    {0x08, 0x7E, 0x09, 0x01, 0x02, 0x00}, // f
    {0x18, 0xA4, 0xA4, 0xA4, 0x7C, 0x00}, // g
    {0x7F, 0x08, 0x04, 0x04, 0x78, 0x00}, // h
    {0x00, 0x44, 0x7D, 0x40, 0x00, 0x00}, // i
    {0x40, 0x80, 0x84, 0x7D, 0x00, 0x00}, // j
    {0x7F, 0x10, 0x28, 0x44, 0x00, 0x00}, // k
    {0x00, 0x41, 0x7F, 0x40, 0x00, 0x00}, // l
    {0x7C, 0x04, 0x18, 0x04, 0x78, 0x00}, // m
    {0x7C, 0x08, 0x04, 0x04, 0x78, 0x00}, // n
    {0x38, 0x44, 0x44, 0x44, 0x38, 0x00}, // o
    {0xFC, 0x24, 0x24, 0x24, 0x18, 0x00}, // p
    {0x18, 0x24, 0x24, 0x18, 0xFC, 0x00}, // q
    {0x7C, 0x08, 0x04, 0x04, 0x08, 0x00}, // r
    {0x48, 0x54, 0x54, 0x54, 0x20, 0x00}, // s
    {0x04, 0x3F, 0x44, 0x40, 0x20, 0x00}, // t
    {0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00}, // u
    {0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00}, // v
    {0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00}, // w
    {0x44, 0x28, 0x10, 0x28, 0x44, 0x00}, // x
    {0x1C, 0xA0, 0xA0, 0xA0, 0x7C, 0x00}, // y
    {0x44, 0x64, 0x54, 0x4C, 0x44, 0x00}, // z
    {0x00, 0x06, 0x09, 0x09, 0x06, 0x00}  // DEL
};

/**
 * @brief 延时函数
 * @param ms 延时毫秒数
 */
void SH1106_Delay_ms(uint32_t ms)
{
    // 使用系统时钟驱动的延时函数
    mspm0_delay_ms(ms);
}

/**
 * @brief 使用SPI硬件CD功能写命令
 * @param cmd 命令字节
 */
void SH1106_WriteCommand(uint8_t cmd)
{
    // 等待SPI空闲
    while(DL_SPI_isBusy(SPI_OLED_INST));
    
    // 设置为命令模式
    DL_SPI_setControllerCommandDataModeConfig(SPI_OLED_INST, DL_SPI_CD_MODE_COMMAND);
    
    // 发送命令
    DL_SPI_transmitData8(SPI_OLED_INST, cmd);
    
    // 等待发送完成
    while(DL_SPI_isBusy(SPI_OLED_INST));
}

/**
 * @brief 使用SPI硬件CD功能写数据
 * @param data 数据字节
 */
void SH1106_WriteData(uint8_t data)
{
    // 等待SPI空闲
    while(DL_SPI_isBusy(SPI_OLED_INST));

    // 设置为数据模式
    DL_SPI_setControllerCommandDataModeConfig(SPI_OLED_INST, DL_SPI_CD_MODE_DATA);

    // 发送数据
    DL_SPI_transmitData8(SPI_OLED_INST, data);

    // 等待发送完成
    while(DL_SPI_isBusy(SPI_OLED_INST));
}

/**
 * @brief 复位SH1106
 */
void SH1106_Reset(void)
{
    // 复位引脚拉低
    DL_GPIO_clearPins(GPIO_OLED_PORT, GPIO_OLED_PIN_RES_PIN);
    SH1106_Delay_ms(100);
    
    // 复位引脚拉高
    DL_GPIO_setPins(GPIO_OLED_PORT, GPIO_OLED_PIN_RES_PIN);
    SH1106_Delay_ms(100);
}

/**
 * @brief 设置光标位置
 * @param x 列位置 (0-127)
 * @param page 页位置 (0-7)
 */
void SH1106_SetCursor(uint8_t x, uint8_t page)
{
    // SH1106需要2列偏移
    uint8_t col = x + 2;
    
    SH1106_WriteCommand(SH1106_CMD_SET_PAGE_START + page);
    SH1106_WriteCommand(SH1106_CMD_SET_COLUMN_LOW + (col & 0x0F));
    SH1106_WriteCommand(SH1106_CMD_SET_COLUMN_HIGH + ((col >> 4) & 0x0F));
}

/**
 * @brief 初始化SH1106 - 重新设计的初始化序列
 */
void SH1106_Init(void)
{
    // 硬件复位
    SH1106_Reset();

    // SH1106初始化序列 - 按数据手册顺序，修正参数
    SH1106_WriteCommand(0xAE);    // 显示关闭
    SH1106_WriteCommand(0x40);    // 设置显示起始行 [0]
    SH1106_WriteCommand(0x81);    // 对比度控制
    SH1106_WriteCommand(0xCF);    // 对比度值 (修正：提高对比度)
    SH1106_WriteCommand(0xA1);    // 设置段重映射 (修正：A1而不是A0)
    SH1106_WriteCommand(0xC8);    // 设置COM输出扫描方向 (修正：C8而不是C0)
    SH1106_WriteCommand(0xA6);    // 正常显示模式
    SH1106_WriteCommand(0xA8);    // 设置复用比(1 to 64)
    SH1106_WriteCommand(0x3F);    // 1/64 duty
    SH1106_WriteCommand(0xD3);    // 设置显示偏移
    SH1106_WriteCommand(0x00);    // 无偏移
    SH1106_WriteCommand(0xD5);    // 设置显示时钟分频/振荡器频率
    SH1106_WriteCommand(0x80);    // 设置分频比
    SH1106_WriteCommand(0xD9);    // 设置预充电周期
    SH1106_WriteCommand(0x22);    // 预充电周期
    SH1106_WriteCommand(0xDA);    // 设置com pins硬件配置
    SH1106_WriteCommand(0x12);    // com pins配置
    SH1106_WriteCommand(0xDB);    // 设置vcomh
    SH1106_WriteCommand(0x35);    // 0.77*vcc
    SH1106_WriteCommand(0x8D);    // 电荷泵设置
    SH1106_WriteCommand(0x14);    // 开启电荷泵
    SH1106_WriteCommand(0xAF);    // 开启显示

    SH1106_Delay_ms(100);

    // 全屏清零 - 确保清空所有显示内容
    for(uint8_t page = 0; page < 8; page++) {
        SH1106_SetCursor(0, page);
        for(uint8_t col = 0; col < 128; col++) {  // SH1106可见区域为128列
            SH1106_WriteData(0x00);
        }
    }

    // 再次确认显示开启
    SH1106_WriteCommand(0xAF);    // 确保显示开启
}

/**
 * @brief 清屏 - 只清缓冲区，需要调用Display()显示
 */
void SH1106_Clear(void)
{
    // 清空缓冲区
    memset(sh1106_buffer, 0, sizeof(sh1106_buffer));
}

/**
 * @brief 立即清屏 - 直接清除屏幕内容
 */
void SH1106_ClearImmediate(void)
{
    // 清空缓冲区
    memset(sh1106_buffer, 0, sizeof(sh1106_buffer));
    
    // 直接清屏 - 修正为从第2列开始，写128列
    for(uint8_t page = 0; page < 8; page++) {
        SH1106_WriteCommand(0xB0 + page);    // 设置页地址
        SH1106_WriteCommand(0x02);           // 设置低列起始地址
        SH1106_WriteCommand(0x10);           // 设置高列起始地址
        for(uint8_t col = 0; col < 128; col++) {
            SH1106_WriteData(0x00);
        }
    }
}

/**
 * @brief 将缓冲区内容显示到屏幕 - 优化版本，添加原子性保护
 */
void SH1106_Display(void)
{
    // 禁用中断保证原子性
    __disable_irq();
    
    for(uint8_t page = 0; page < SH1106_PAGES; page++) {
        SH1106_SetCursor(0, page);
        for(uint8_t x = 0; x < SH1106_WIDTH; x++) {
            SH1106_WriteData(sh1106_buffer[page][x]);
        }
    }
    
    // 恢复中断
    __enable_irq();
}

/**
 * @brief 设置像素点
 * @param x 横坐标 (0-127)
 * @param y 纵坐标 (0-63)
 * @param color 颜色 (0=黑, 1=白)
 */
void SH1106_SetPixel(uint8_t x, uint8_t y, uint8_t color)
{
    if(x >= SH1106_WIDTH || y >= SH1106_HEIGHT) return;
    
    uint8_t page = y / 8;
    uint8_t bit = y % 8;
    
    if(color) {
        sh1106_buffer[page][x] |= (1 << bit);
    } else {
        sh1106_buffer[page][x] &= ~(1 << bit);
    }
}

/**
 * @brief 绘制字符
 * @param x 起始横坐标
 * @param page 页位置
 * @param ch 要显示的字符
 * @param font_size 字体大小
 */
void SH1106_DrawChar(uint8_t x, uint8_t page, char ch, sh1106_font_size_t font_size)
{
    if(x >= SH1106_WIDTH || page >= SH1106_PAGES) return;
    
    if(ch < 32 || ch > 126) ch = 32; // 限制字符范围
    
    uint8_t char_index = ch - 32;
    
    if(font_size == FONT_SIZE_6x8) {
        for(uint8_t i = 0; i < 6 && (x + i) < SH1106_WIDTH; i++) {
            sh1106_buffer[page][x + i] = font_6x8[char_index][i];
        }
    }
}

/**
 * @brief 绘制字符串
 * @param x 起始横坐标
 * @param page 页位置
 * @param str 要显示的字符串
 * @param font_size 字体大小
 */
void SH1106_DrawString(uint8_t x, uint8_t page, const char *str, sh1106_font_size_t font_size)
{
    uint8_t char_width = (font_size == FONT_SIZE_6x8) ? 6 : 8;
    
    while(*str && x < SH1106_WIDTH) {
        SH1106_DrawChar(x, page, *str, font_size);
        x += char_width;
        str++;
    }
}

/**
 * @brief 绘制直线
 * @param x1,y1 起点坐标
 * @param x2,y2 终点坐标
 * @param color 颜色
 */
void SH1106_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color)
{
    int16_t dx = x2 > x1 ? x2 - x1 : x1 - x2;
    int16_t dy = y2 > y1 ? y2 - y1 : y1 - y2;
    int16_t sx = x1 < x2 ? 1 : -1;
    int16_t sy = y1 < y2 ? 1 : -1;
    int16_t err = dx - dy;
    int16_t e2;
    
    while(1) {
        SH1106_SetPixel(x1, y1, color);
        
        if(x1 == x2 && y1 == y2) break;
        
        e2 = 2 * err;
        if(e2 > -dy) {
            err -= dy;
            x1 += sx;
        }
        if(e2 < dx) {
            err += dx;
            y1 += sy;
        }
    }
}

/**
 * @brief 绘制矩形边框
 * @param x,y 左上角坐标
 * @param width,height 宽度和高度
 * @param color 颜色
 */
void SH1106_DrawRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color)
{
    // 上边
    SH1106_DrawLine(x, y, x + width - 1, y, color);
    // 下边
    SH1106_DrawLine(x, y + height - 1, x + width - 1, y + height - 1, color);
    // 左边
    SH1106_DrawLine(x, y, x, y + height - 1, color);
    // 右边
    SH1106_DrawLine(x + width - 1, y, x + width - 1, y + height - 1, color);
}

/**
 * @brief 绘制填充矩形
 * @param x,y 左上角坐标
 * @param width,height 宽度和高度
 * @param color 颜色
 */
void SH1106_FillRectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color)
{
    for(uint8_t i = 0; i < height; i++) {
        SH1106_DrawLine(x, y + i, x + width - 1, y + i, color);
    }
}

/**
 * @brief 设置对比度
 * @param contrast 对比度值 (0-255)
 */
void SH1106_SetContrast(uint8_t contrast)
{
    SH1106_WriteCommand(SH1106_CMD_SET_CONTRAST);
    SH1106_WriteCommand(contrast);
}

/**
 * @brief 开启显示
 */
void SH1106_DisplayOn(void)
{
    SH1106_WriteCommand(SH1106_CMD_DISPLAY_ON);
}

/**
 * @brief 关闭显示
 */
void SH1106_DisplayOff(void)
{
    SH1106_WriteCommand(SH1106_CMD_DISPLAY_OFF);
}

/**
 * @brief 反色显示
 * @param invert true=反色, false=正常
 */
void SH1106_InvertDisplay(bool invert)
{
    if(invert) {
        SH1106_WriteCommand(0xA7); // 反色显示
    } else {
        SH1106_WriteCommand(SH1106_CMD_NORMAL_DISPLAY); // 正常显示
    }
} 